package gdupt.utils;

import gdupt.stack.OperationStack;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhn
 */
public class Calculate {

    /**
     * 参数为中缀表达式
     *
     * @param zz
     * @return
     */
    public String[] getHZExpression(String zz) {
        List<String> list = new ArrayList<String>();
        //符号运算顺序
        Map<String, Integer> ExOrder = new HashMap<String, Integer>();
        ExOrder.put("+", 10);
        ExOrder.put("-", 10);
        ExOrder.put("*", 20);
        ExOrder.put("/", 20);
        //创建一个符号栈
        OperationStack<String> stack_symbol = new OperationStack<String>();

        StringBuffer sb = new StringBuffer();
        //循环得到的运算字符串
        for (int i = 0; i < zz.length(); i++) {

            //处理数字部分
            if (Character.isDigit(zz.charAt(i)) || zz.charAt(i) == '.') {
                sb.append(String.valueOf(zz.charAt(i)));
                continue;
            }
            //遇到符号将数字部分放入到表达式中
            if (sb != null && sb.length() != 0) {
                list.add(sb.toString());
                sb.setLength(0);
            }
            //符号信息处理
            String sy = String.valueOf(zz.charAt(i));
            //如果符号栈为空，或者符号为“(”直接放入符号栈中
            if (stack_symbol.stackSize() == 0 || stack_symbol.top().equals("(") || sy.equals("(")) {
                stack_symbol.push(sy);
            } else if (sy.equals(")")) {
                while (!stack_symbol.top().equals("(")) {
                    list.add(stack_symbol.pop());
                }
                //遇到“（”后，将其出栈
                stack_symbol.pop();
            } else if (ExOrder.get(sy) == null) {
                System.out.println("解析出现异常，四则运算格式异常，请重新核对!!~~~~");
            } else if (ExOrder.get(sy) >= ExOrder.get(stack_symbol.top())) {
                stack_symbol.push(sy);
            } else if (ExOrder.get(sy) < ExOrder.get(stack_symbol.top())) {
                while (stack_symbol.stackSize() != 0 && !stack_symbol.top().equals("(") && ExOrder.get(sy) <= ExOrder.get(stack_symbol.top())) {
                    list.add(stack_symbol.pop());
                }
                stack_symbol.push(sy);
            } else {
                System.out.println("出现其他情况信息,请处理");
            }

        }
        //循环结束后，数字没有放入表达式的，放入后缀表达式中
        if (sb != null && sb.length() != 0) {
            list.add(sb.toString());
            sb.setLength(0);
        }
        //循环结束后，将没有处理的元素依次出栈，放入后缀表达式中;
        while (stack_symbol.stackSize() != 0) {
            list.add(stack_symbol.pop());
        }
        //将输出的数组转化为字符串就是后缀表达式了
        return list.toArray(new String[list.size()]);
    }


    /**
     * 后缀表达式运算,参数是后缀表达式数组
     *
     * @param hzArr
     * @return
     */
    public Double HZOperation(String[] hzArr) {
        //创建一个数字栈
        OperationStack<Double> stack_number = new OperationStack<Double>();
        //使用正则表达式判断实时该字符是否为数字类型(是否可以转化为数值类型)
        String regex = "-[0-9]+(.[0-9]+)?|[0-9]+(.[0-9]+)?";
        for (String hz : hzArr) {
            //判断，如果为数字，则入栈
            if (hz.matches(regex)) {
                stack_number.push(Double.parseDouble(hz));
                continue;
            }
            //如果为符号，从栈顶依次取两个元素进行运算。第一个取出的元素作为减数与除数,进行四则运算
            double dou = getArithmetic(stack_number.pop(), stack_number.pop(), hz);
            //将运算结果入栈
            stack_number.push(dou);
        }
        //将最终栈顶结果作为运算结果输出
        return stack_number.pop();
    }

    //四则运算（目前只有 + - * / ）
    public double getArithmetic(double num1, double num2, String fh) {
        //在后缀表达式运算时，需要把栈顶的数字最为减数或除数，所有我们将参数1作为减数或除数
        //当然，你要不按照这个顺序也可以。
        switch (fh) {
            case "+":
                return num2 + num1;
            case "-":
                return num2 - num1;
            case "*":
                return num2 * num1;
            case "/":
                return num2 / num1;
            default:
                System.out.println("需要计算的表达式不正确 , 请重试");
                return 0;
        }
    }
}
